home *** CD-ROM | disk | FTP | other *** search
/ Aminet 5 / Aminet 5 - March 1995.iso / Aminet / comm / tcp / ATCP_src_22.lha / AmiTCP-2.2 / src / amitcp / net / sana2arp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-11-06  |  21.3 KB  |  829 lines

  1. RCS_ID_C="$Id: sana2arp.c,v 1.15 1993/10/29 02:00:50 ppessi Exp $";
  2. /*
  3.  * Copyright (c) 1993 AmiTCP/IP Group, <amitcp-group@hut.fi>,
  4.  *                    Helsinki University of Technology, Finland.
  5.  *                    All rights reserved.
  6.  *
  7.  * sana2arp.c - ARP for Sana-II Interfaces
  8.  *
  9.  * Last modified: Fri Oct 29 01:50:30 1993 ppessi
  10.  *
  11.  * HISTORY
  12.  * $Log: sana2arp.c,v $
  13.  * Revision 1.15  1993/10/29  02:00:50  ppessi
  14.  * Fixed ARP table entry allocation policy.
  15.  *
  16.  * Revision 1.15  1993/10/29  02:00:50  ppessi
  17.  * Fixed ARP table entry allocation policy.
  18.  *
  19.  * Revision 1.14  1993/06/04  11:16:15  jraja
  20.  * Fixes for first public release.
  21.  *
  22.  * Revision 1.13  1993/05/16  21:09:43  ppessi
  23.  * RCS version changed.
  24.  *
  25.  * Revision 1.12  1993/05/05  16:10:33  puhuri
  26.  * Fixes for final demo.
  27.  *
  28.  * Revision 1.11  93/05/04  10:52:51  10:52:51  ppessi (Pekka Pessi)
  29.  * A version with separate ARP tables for each interface.
  30.  * 
  31.  * Revision 1.10  93/04/21  00:03:53  00:03:53  ppessi (Pekka Pessi)
  32.  * ARP works with Ethernet. 
  33.  * 
  34.  * Revision 1.9  93/04/19  02:41:31  02:41:31  ppessi (Pekka Pessi)
  35.  * Test version. In principle this is not ethernet dependent...
  36.  * 
  37.  * Revision 1.8  93/04/05  19:03:25  19:03:25  jraja (Jarno Tapio Rajahalme)
  38.  * Changed storage of the spl functions  return values to type spl_t.
  39.  * Added include for conf.h to every .c file.
  40.  * 
  41.  * Revision 1.7  93/03/22  16:54:24  16:54:24  jraja (Jarno Tapio Rajahalme)
  42.  * Changed bcopy()s and bzero()s with word aligned pointers to
  43.  * aligned_b(copy|zero) ar aligned_b(copy|zero)_const. The latter is for calls
  44.  * in which the size is constant.
  45.  * These can be disabled by defining NOALIGN.
  46.  *   Converted bcopy()s doing structure copies (on aligned pointers) 
  47.  * to structure assignments, since at least SASC produces better code
  48.  * with assignment.
  49.  * 
  50.  * Revision 1.6  93/03/20  07:13:42  07:13:42  ppessi (Pekka Pessi)
  51.  * removed trailer type negotiating 
  52.  * 
  53.  * Revision 1.5  93/03/13  17:13:55  17:13:55  ppessi (Pekka Pessi)
  54.  * Fixed bugs with variable initialization.
  55.  * 
  56.  * Revision 1.4  93/03/03  20:49:23  20:49:23  jraja (Jarno Tapio Rajahalme)
  57.  * Added #include <net/if_sana.h>
  58.  * 
  59.  * Revision 1.3  93/03/02  18:31:34  18:31:34  too (Tomi Ollila)
  60.  * Changed %? to %l? on format strings
  61.  * 
  62.  * Revision 1.2  93/03/02  18:15:19  18:15:19  ppessi (Pekka Pessi)
  63.  * Broadcast non-ether-specific
  64.  * 
  65.  * Revision 1.1  93/03/02  15:15:00  15:15:00  ppessi (Pekka Pessi)
  66.  * Changed name, added sana_sprintf()
  67.  * 
  68.  * HISTORY AS "netinet/if_arp.c"
  69.  * Revision 1.2  93/02/26  08:50:10  08:50:10  jraja (Jarno Tapio Rajahalme)
  70.  * Made this compile with ANSI C.
  71.  * Initialized 'at' to NULL in function in_arpinput, since it might have been
  72.  * used without initialization (see reply: label).
  73.  * 
  74.  * Revision 1.1  92/11/17  16:28:04  16:28:04  jraja (Jarno Tapio Rajahalme)
  75.  * Initial revision
  76.  */
  77.  
  78. /*
  79.  * Address Resolution Protocol.
  80.  * TODO:
  81.  *    add "inuse/lock" bit (or ref. count) along with valid bit
  82.  */
  83.  
  84. #include <conf.h>
  85.  
  86. #include <sys/param.h>
  87. #include <sys/systm.h>
  88. #include <sys/malloc.h>
  89. #include <sys/mbuf.h>
  90. #include <sys/socket.h>
  91. #include <sys/time.h>
  92. #include <sys/kernel.h>
  93. #include <sys/errno.h>
  94. #include <sys/ioctl.h>
  95. #include <sys/syslog.h>
  96. #include <sys/synch.h>
  97.  
  98. #include <net/if.h>
  99. #include <net/if_types.h>
  100. #include <netinet/in.h>
  101. #include <netinet/in_systm.h>
  102. #include <netinet/in_var.h>
  103. #include <netinet/ip.h>
  104.  
  105. #include <net/if_sana.h>
  106. #include <net/sana2arp.h>
  107.  
  108. #include <net/if_loop_protos.h>
  109.  
  110. /*
  111.  * Internet to hardware address resolution table entry
  112.  */
  113. struct    arptab {
  114.   struct arptab *at_succ;    /* doubly linked list */
  115.   struct arptab *at_pred;
  116.   struct in_addr at_iaddr;    /* internet address */
  117.   u_char         at_hwaddr[MAXADDRSANA]; /* hardware address */
  118.   u_char         at_timer;    /* minutes since last reference */
  119.   u_char         at_flags;    /* flags */
  120.   struct mbuf   *at_hold;    /* last packet until resolved/timeout */
  121. };
  122.  
  123. /*
  124.  * Global constant for ARP entry allocation
  125.  */
  126. unsigned long arpentries = ARPENTRIES;
  127.  
  128. /*
  129.  * General per interface hash table
  130.  */
  131. struct arptable {
  132.   struct SignalSemaphore atb_lock;
  133.   struct arptab         *atb_free;
  134.   struct MinList         atb_entries[ARPTAB_HSIZE];
  135. };
  136.  
  137. #define ARPTAB_LOCK(atb) (ObtainSemaphore(&atb->atb_lock))
  138. #define ARPTAB_UNLOCK(atb) (ReleaseSemaphore(&atb->atb_lock)) 
  139. #define    ARPTAB_HASH(a) ((u_long)(a) % ARPTAB_HSIZE)
  140.  
  141. extern struct ifnet loif;
  142.  
  143. int    useloopback = 0;    /* use loopback interface for local traffic */
  144.  
  145. static void arpwhohas(register struct sana_softc *ssc, struct in_addr * addr);
  146. static void in_arpinput(register struct sana_softc *ssc, struct mbuf *m);
  147. static char *sana_sprintf(register u_char *ap, int len);
  148.  
  149. /*
  150.  * Initialization routine. Allocate ARP entries.
  151.  * MUST BE CALLED AT SPLIMP.
  152.  */
  153. void
  154. alloc_arptable(struct sana_softc* ssc, int to_allocate)
  155. {
  156.   struct arptab *at;
  157.   struct arptable *atab;
  158.   int i;
  159.   
  160.   if (ssc->ss_arp.table) 
  161.     return (void)ssc->ss_arp.table;
  162.  
  163. #if 0
  164.   if (to_allocate < arpentries)
  165. #endif
  166.       to_allocate = arpentries;
  167.     
  168.   atab = bsd_malloc(sizeof(*atab), M_ARPENT, M_WAITOK);
  169.   at = bsd_malloc(sizeof(*at) * to_allocate, M_ARPENT, M_WAITOK);
  170.  
  171.   if (atab && at) {
  172.     InitSemaphore(&atab->atb_lock);
  173.     for (i = 0; i < ARPTAB_HSIZE; i++)
  174.       NewList((struct List *)(atab->atb_entries + i));
  175.  
  176.     aligned_bzero(at, sizeof(*at) * to_allocate);
  177.  
  178.     at[0].at_succ = NULL;
  179.     for (i = 1; i < to_allocate; i++) {
  180.       at[i].at_succ = &at[i - 1];
  181.     }
  182.     atab->atb_free = &at[to_allocate - 1];
  183.   } else {
  184.     if (atab) bsd_free(atab, M_ARPENT);
  185.     if (at) bsd_free(at, M_ARPENT);
  186.     log(LOG_ERR, "Could not allocate ARP table for %s\n", ssc->ss_name);
  187.   }
  188.  
  189.   ssc->ss_arp.table = atab;
  190. }
  191.  
  192. /* 
  193.  * Notification function for arp entries 
  194.  */
  195. LONG 
  196. arpentries_notify(void *dummy, LONG value)
  197. {
  198.   return (ULONG)value > ARPENTRIES_MIN;
  199. }
  200.  
  201. /*
  202.  * Free an arptab entry. ARP TABLE MUST BE LOCKED
  203.  */
  204. static void
  205. arptfree(register struct arptable *atb, register struct arptab *at)
  206. {
  207.   if (at->at_hold)
  208.     m_freem(at->at_hold);
  209.  
  210.   Remove((struct Node *)at);
  211.  
  212.   if (at->at_flags & ATF_PERM) {
  213.     bsd_free(at, M_ARPENT);
  214.   } else {
  215.     at->at_hold = NULL;
  216.     at->at_timer = at->at_flags = 0;
  217.     at->at_iaddr.s_addr = 0;
  218.     at->at_succ = atb->atb_free;
  219.     atb->atb_free = at;
  220.   }
  221. }
  222.  
  223. /*
  224.  * Enter a new address in arptab. ARP TABLE MUST BE LOCKED
  225.  */
  226. static struct arptab *
  227. arptnew(u_long addr, struct arptable *atb, int permanent)
  228. {
  229.   struct arptab *at = NULL;
  230.  
  231.   if (permanent) {
  232.     at = bsd_malloc(sizeof(*at), M_ARPENT, M_WAITOK);
  233.     bzero((caddr_t)at, sizeof(*at));
  234.   } else {
  235.     at = atb->atb_free;
  236.     if (at) {
  237.       atb->atb_free = at->at_succ;
  238.     } else {
  239.       /*
  240.        * The the oldest entry is pushed out from the 
  241.        * interface table if there is no free entry.
  242.        * This should always succeed since all 
  243.        * entries can not be permanent
  244.        */
  245.       struct arptab *oldest = NULL;
  246.       int i;
  247.  
  248.       for (i = 0; i < ARPTAB_HSIZE; i++) {
  249.     for (at = (struct arptab *)atb->atb_entries[i].mlh_Head; 
  250.          at->at_succ; 
  251.          at = at->at_succ) {
  252.       if (at->at_flags == 0 || (at->at_flags & ATF_PERM))
  253.         continue;
  254.       if (!oldest || oldest->at_timer < at->at_timer)
  255.         oldest = at;
  256.     }
  257.       }
  258.       if (oldest) {
  259.     Remove((struct Node *)oldest);
  260.     at = oldest;
  261.       } else {
  262.     at = NULL;
  263.       }
  264.     }
  265.   }
  266.   if (at) {
  267.     at->at_iaddr.s_addr = addr;
  268.     at->at_flags = ATF_INUSE;
  269.     AddHead((struct List *)(&atb->atb_entries[ARPTAB_HASH(addr)]), 
  270.         (struct Node *)at);
  271.   }
  272.   return (at);
  273. }
  274.  
  275. /*
  276.  * Locate an IP address in the ARP table
  277.  * Assume looker have locked the table
  278.  */
  279. static struct arptab*
  280. arptab_look(struct arptable *table, u_long addr)
  281. {
  282.   register struct arptab *at = (struct arptab *)
  283.     table->atb_entries[ARPTAB_HASH(addr)].mlh_Head; 
  284.  
  285.   for(;at->at_succ; at = at->at_succ) 
  286.     if (at->at_iaddr.s_addr == addr) 
  287.       return at;
  288.  
  289.   return NULL;
  290. }
  291.  
  292. /*
  293.  * Timeout routine.  Age arp_tab entries once a minute.
  294.  */
  295. void
  296. arptimer()
  297. {
  298.   struct sana_softc *ssc;
  299.   register struct arptable *atab;
  300.   register struct arptab *at, *oldest;
  301.   register i;
  302.  
  303.   for (ssc = ssq; ssc; ssc = ssc->ss_next) {
  304.     if (!(atab = ssc->ss_arp.table))
  305.       continue;
  306.     /* Lock the table */
  307.     ARPTAB_LOCK(atab);
  308.     oldest = NULL;
  309.     for (i = 0; i < ARPTAB_HSIZE; i++) {
  310.       for (at = (struct arptab *)atab->atb_entries[i].mlh_Head; 
  311.        at->at_succ; 
  312.        at = at->at_succ) {
  313.     if (at->at_flags == 0 || (at->at_flags & ATF_PERM))
  314.       continue;
  315.     if (++at->at_timer < ((at->at_flags & ATF_COM) ?
  316.                   ARPT_KILLC : ARPT_KILLI))
  317.       continue;
  318.     /* timer has expired, clear entry */
  319.     arptfree(atab, at);
  320.       }
  321.     }
  322.     ARPTAB_UNLOCK(atab);
  323.   }
  324. }
  325.  
  326. /*
  327.  * Broadcast an ARP packet, asking who has addr on interface ssc.
  328.  */
  329. static void
  330. arpwhohas(register struct sana_softc *ssc, struct in_addr *addr)
  331. {
  332.   register struct mbuf *m;
  333.   register struct s2_arppkt *s2a;
  334.   struct sockaddr_sana2 ss2;
  335.  
  336.   if ((m = m_gethdr(M_DONTWAIT, MT_DATA)) == NULL)
  337.     return;
  338.   m->m_len = sizeof(*s2a);
  339.   m->m_pkthdr.len = sizeof(*s2a);
  340.   MH_ALIGN(m, sizeof(*s2a));
  341.   s2a = mtod(m, struct s2_arppkt *);
  342.   aligned_bzero_const((caddr_t)s2a, sizeof (*s2a));
  343.   m->m_flags |= M_BCAST;
  344.  
  345.   /* fill in header depending of the interface */
  346.   s2a->arp_hrd = ssc->ss_arp.hrd;
  347.   s2a->arp_pro = htons(ssc->ss_ip.type);
  348.   s2a->arp_pln = sizeof(struct in_addr); /* protocol address length */
  349.   s2a->arp_hln = ssc->ss_if.if_addrlen;  /* hardware address length */
  350.   s2a->arp_op = htons(ARPOP_REQUEST);
  351.  
  352.   /* Copy source hardware address */
  353.   bcopy((caddr_t)ssc->ss_hwaddr, 
  354.     (caddr_t)&s2a->arpdata, 
  355.     s2a->arp_hln);
  356.   /* Copy source protocol address */
  357.   bcopy((caddr_t)&ssc->ss_ipaddr, 
  358.     (caddr_t)&s2a->arpdata + s2a->arp_hln, 
  359.     s2a->arp_pln);
  360.   /* Zero target hardware address */
  361.   bzero((caddr_t)&s2a->arpdata + s2a->arp_hln + s2a->arp_pln, 
  362.     s2a->arp_hln);
  363.   /* Copy target protocol address */
  364.   bcopy((caddr_t)addr, 
  365.     (caddr_t)&s2a->arpdata + 2 * s2a->arp_hln + s2a->arp_pln, 
  366.     s2a->arp_pln);
  367.  
  368.   /* Send an ARP packet */
  369.   ss2.ss2_len = sizeof(ss2);
  370.   ss2.ss2_family = AF_UNSPEC;
  371.   ss2.ss2_type = ssc->ss_arp.type; 
  372.   (*ssc->ss_if.if_output)(&ssc->ss_if, m, (struct sockaddr *)&ss2, 
  373.               (struct rtentry *)0);
  374. }
  375.  
  376. /*
  377.  * Resolve an IP address into an SANA-II address.  If success, 
  378.  * desten is filled in.  If there is no entry in arptab,
  379.  * set one up and broadcast a request for the IP address.
  380.  * Hold onto this mbuf and resend it once the address
  381.  * is finally resolved.  A return value of 1 indicates
  382.  * that desten has been filled in and the packet should be sent
  383.  * normally; a 0 return indicates that the packet has been
  384.  * taken over here, either now or for later transmission.
  385.  *
  386.  * We do some (conservative) locking here at splimp, since
  387.  * arptab is also altered from sana poll routine 
  388.  */
  389. int
  390. arpresolve(register struct sana_softc *ssc,
  391.        struct mbuf *m,
  392.        register struct in_addr *destip,
  393.        register u_char *desten,
  394.        int *error)
  395. {
  396.   register struct arptab *at;
  397.   register struct arptable *atb;
  398.   struct sockaddr_in sin;
  399.   register struct in_ifaddr *ia;
  400.   u_long lna;
  401.  
  402.   if (m->m_flags & M_BCAST) {    /* broadcast */
  403.     return 1;
  404.   }
  405.   lna = in_lnaof(*destip);
  406.   /* if for us, use software loopback driver if up */
  407.   for (ia = in_ifaddr; ia; ia = ia->ia_next)
  408.     if ((ia->ia_ifp == &ssc->ss_if) &&
  409.     (destip->s_addr == ia->ia_addr.sin_addr.s_addr)) {
  410.       /*
  411.        * This test used to be
  412.        *    if (loif.if_flags & IFF_UP)
  413.        * It allowed local traffic to be forced
  414.        * through the hardware by configuring the loopback down.
  415.        * However, it causes problems during network configuration
  416.        * for boards that can't receive packets they send.
  417.        * It is now necessary to clear "useloopback"
  418.        * to force traffic out to the hardware.
  419.        */
  420.       if (useloopback) {
  421.     sin.sin_family = AF_INET;
  422.     sin.sin_addr = *destip;
  423.     (void) looutput(&loif, m, (struct sockaddr *)&sin, 0);
  424.     /*
  425.      * The packet has already been sent and freed.
  426.      */
  427.     return (0);
  428.       } else {
  429.     bcopy((caddr_t)ssc->ss_hwaddr, (caddr_t)desten, ssc->ss_if.if_addrlen);
  430.     return (1);
  431.       }
  432.     }
  433.  
  434.   if (ssc->ss_if.if_flags & IFF_NOARP) {
  435.     /* No arp */
  436.     log(LOG_ERR, 
  437.     "arpresolve: can't resolve address for if %s/%ld\n", 
  438.     ssc->ss_if.if_name, ssc->ss_if.if_unit);
  439.     *error = ENETUNREACH;
  440.     m_freem(m);
  441.     return (0);
  442.   } 
  443.  
  444.   /* Try to locate ARP table */ 
  445.   if (!(atb = ssc->ss_arp.table)) {
  446.     alloc_arptable(ssc, 0);
  447.     if (!(atb = ssc->ss_arp.table)) {
  448.       log(LOG_ERR, "arpresolve: memory exhausted");
  449.       *error = ENOBUFS; 
  450.       m_free(m); 
  451.       return 0;
  452.     }
  453.   }
  454.  
  455.   ARPTAB_LOCK(atb);
  456.   at = arptab_look(atb, destip->s_addr);
  457.   if (at == 0) {        /* not found */
  458.     at = arptnew(destip->s_addr, atb, FALSE);
  459.     if (at) {
  460.       at->at_hold = m;
  461.       arpwhohas(ssc, destip);
  462.     } else {
  463.       log(LOG_ERR, "arpresolve: no free entry");
  464.       *error = ENETUNREACH;
  465.       m_free(m); 
  466.     } 
  467.     ARPTAB_UNLOCK(atb);
  468.     return 0;
  469.   }
  470.  
  471.   at->at_timer = 0;        /* restart the timer */
  472.   if (at->at_flags & ATF_COM) {    /* entry IS complete */
  473.     bcopy((caddr_t)at->at_hwaddr, (caddr_t)desten, ssc->ss_if.if_addrlen);
  474.     ARPTAB_UNLOCK(atb);
  475.     return 1;
  476.   }
  477.   /*
  478.    * There is an arptab entry, but no address response yet.  
  479.    * Replace the held mbuf with this latest one.
  480.    */
  481.   if (at->at_hold)
  482.     m_freem(at->at_hold);
  483.   at->at_hold = m;
  484.   arpwhohas(ssc, destip);    /* ask again */
  485.   ARPTAB_UNLOCK(atb);
  486.   return 0;
  487. }
  488.  
  489. /*
  490.  * Called from the sana poll routine
  491.  * when ARP type packet is received.  
  492.  * Common length and type checks are done here,
  493.  * then the protocol-specific routine is called.
  494.  * In addition, a sanity check is performed on the sender
  495.  * protocol address, to catch impersonators.
  496.  */
  497. void
  498. arpinput(struct sana_softc *ssc,
  499.     struct mbuf *m,
  500.         caddr_t srcaddr)
  501. {
  502.   register struct arphdr *ar;
  503.   int proto;
  504.  
  505.   if (ssc->ss_if.if_flags & IFF_NOARP)
  506.     goto out;
  507.   if (m->m_len < sizeof(struct arphdr))
  508.     goto out;
  509.   ar = mtod(m, struct arphdr *);
  510.   if (ntohs(ar->ar_hrd) != ssc->ss_arp.hrd)
  511.     goto out;
  512.   if (m->m_len < sizeof(struct arphdr) + 2 * ar->ar_hln + 2 * ar->ar_pln)
  513.     goto out;
  514.   if (ar->ar_hln != ssc->ss_if.if_addrlen) 
  515.     goto out;
  516.   /* Sanity check */
  517.   if (bcmp(srcaddr, (UBYTE*)ar + sizeof(*ar), ar->ar_hln)) {
  518.     log(LOG_ERR, "An ARP packet sent as %s", 
  519.     sana_sprintf(srcaddr, ar->ar_hln));
  520.     log(LOG_ERR, " from address: %s!!\n", 
  521.     sana_sprintf((UBYTE*)ar + sizeof(*ar), ar->ar_hln));
  522.     goto out;
  523.   }
  524.  
  525.   proto = ntohs(ar->ar_pro);
  526.  
  527.   if (proto == ssc->ss_ip.type) {
  528.     in_arpinput(ssc, m);
  529.     return;
  530.   } 
  531.  
  532.  out:
  533.   m_freem(m);
  534. }
  535.  
  536. /*
  537.  * ARP for Internet protocols on SANA-II interfaces.
  538.  * Algorithm is that given in RFC 826.
  539.  */
  540. static void
  541. in_arpinput(register struct sana_softc *ssc,
  542.         struct mbuf *m)
  543. {
  544.   register struct s2_arppkt *s2a;
  545.   struct sockaddr_in sin;
  546.   struct in_addr isaddr, itaddr, myaddr;
  547.   int op, completed = 0;
  548.   caddr_t sha, spa, tha, tpa;
  549.   size_t  len = ssc->ss_if.if_addrlen;
  550.  
  551.   s2a = mtod(m, struct s2_arppkt *);
  552.   op = ntohs(s2a->arp_op);
  553.  
  554.   if (s2a->arp_pln != sizeof(struct in_addr))
  555.     goto out;
  556.  
  557.   sha = (caddr_t)&(s2a->arpdata); /* other members must be calculated */
  558.   bcopy(spa = sha + len, (caddr_t)&isaddr, sizeof (isaddr));
  559.   tha = spa + sizeof(struct in_addr);
  560.   bcopy(tpa = tha + len, (caddr_t)&itaddr, sizeof (itaddr));
  561.  
  562.  
  563.   {
  564.     register struct in_ifaddr *ia;
  565.     struct in_ifaddr *maybe_ia = 0;
  566.  
  567.     /* Check for our own ARP packets */
  568.     for (ia = in_ifaddr; ia; ia = ia->ia_next)
  569.       if (ia->ia_ifp == &ssc->ss_if) {
  570.     maybe_ia = ia;
  571.     if ((itaddr.s_addr == ia->ia_addr.sin_addr.s_addr) ||
  572.         (isaddr.s_addr == ia->ia_addr.sin_addr.s_addr))
  573.       break;
  574.       }
  575.     if (maybe_ia == 0)
  576.       goto out;
  577.     myaddr = ia ? ia->ia_addr.sin_addr : maybe_ia->ia_addr.sin_addr;
  578.     if (!bcmp(sha, (caddr_t)ssc->ss_hwaddr, len))
  579.       goto out;            /* it's from me, ignore it. */
  580.   }
  581. #ifndef AMITCP
  582.   if (!bcmp(sha, (caddr_t)etherbroadcastaddr, ac->ac_if.if_addrlen)) {
  583.     log(LOG_ERR,
  584.     "arp: ether address is broadcast for IP address %lx!\n",
  585.     ntohl(isaddr.s_addr));
  586.     goto out;
  587.   }
  588. #endif
  589.  
  590.   /* Check for duplicate IP addresses */
  591.   if (isaddr.s_addr == myaddr.s_addr) {
  592.     log(LOG_ERR,
  593.     "duplicate IP address %lx!! sent from hardware address: %s\n",
  594.     ntohl(isaddr.s_addr), 
  595.     sana_sprintf(sha, len));
  596.     itaddr = myaddr;
  597.     if (op == ARPOP_REQUEST)
  598.       goto reply;
  599.     goto out;
  600.   }
  601.   
  602.   {
  603.     struct arptable *atb;
  604.     register struct arptab *at = NULL; /* same as "merge" flag */
  605.     
  606.     /* Try to locate ARP table */ 
  607.     if (!(atb = ssc->ss_arp.table)) {
  608.       goto reply;
  609.     }
  610.  
  611.     ARPTAB_LOCK(atb);
  612.     at = arptab_look(atb, isaddr.s_addr);
  613.  
  614.     if (at) {
  615.       bcopy(sha, (caddr_t)at->at_hwaddr, len);
  616.       if ((at->at_flags & ATF_COM) == 0)
  617.     completed = 1;
  618.       at->at_flags |= ATF_COM;
  619.       if (at->at_hold) {
  620.     sin.sin_family = AF_INET;
  621.     sin.sin_addr = isaddr;
  622.     (*ssc->ss_if.if_output)(&ssc->ss_if, at->at_hold,
  623.                    (struct sockaddr *)&sin, (struct rtentry *)0);
  624.     at->at_hold = 0;
  625.       }
  626.     }
  627.     if (at == 0 && itaddr.s_addr == myaddr.s_addr) {
  628.       /* ensure we have a table entry */
  629.       if (at = arptnew(isaddr.s_addr, atb, FALSE)) {
  630.     bcopy(sha, (caddr_t)at->at_hwaddr, len);
  631.     completed = 1;
  632.     at->at_flags |= ATF_COM;
  633.       }
  634.     }
  635.     ARPTAB_UNLOCK(atb);
  636.   }
  637.  
  638.  reply:
  639.   /*
  640.    * Reply if this is an IP request
  641.    */
  642.   if (op != ARPOP_REQUEST) 
  643.     goto out;
  644.  
  645.   if (itaddr.s_addr == myaddr.s_addr) {
  646.     /* I am the target */
  647.     bcopy(sha, tha, len);
  648.     bcopy((caddr_t)ssc->ss_hwaddr, sha, len);
  649.   } else {
  650.     /* Answer if we have a public entry */
  651.     register struct arptab *at;
  652.     
  653.     /* Try to locate ARP table */ 
  654.     if (!ssc->ss_arp.table)
  655.       goto out;
  656.  
  657.     ARPTAB_LOCK(ssc->ss_arp.table);
  658.     at = arptab_look(ssc->ss_arp.table, itaddr.s_addr);
  659.     if (at && (at->at_flags & ATF_PUBL)) {
  660.       bcopy(sha, tha, len);
  661.       bcopy(at->at_hwaddr, sha, len);
  662.     } else {
  663.       at = NULL;
  664.     }
  665.     ARPTAB_UNLOCK(ssc->ss_arp.table);
  666.     if (!at) 
  667.       goto out;
  668.   }
  669.   {
  670.     struct sockaddr_sana2 ss2;
  671.     bcopy(spa, tpa, sizeof(struct in_addr));
  672.     bcopy((caddr_t)&itaddr, spa, sizeof(struct in_addr));
  673.     s2a->arp_op = htons(ARPOP_REPLY); 
  674.  
  675.     ss2.ss2_len = sizeof(ss2);
  676.     ss2.ss2_family = AF_UNSPEC;
  677.     ss2.ss2_type = ssc->ss_arp.type;
  678.     bcopy(tha, ss2.ss2_host, len);
  679.  
  680.     m->m_flags &= ~(M_BCAST|M_MCAST);
  681.  
  682.     (*ssc->ss_if.if_output)(&ssc->ss_if, m, (struct sockaddr *)&ss2, 
  683.                 (struct rtentry *)0);
  684.     return;
  685.   }
  686.  out:
  687.   m_freem(m);
  688.   return;
  689. }
  690.  
  691. int
  692. arpioctl(cmd, data)
  693.     int cmd;
  694.     caddr_t data;
  695. {
  696.   register struct arpreq *ar = (struct arpreq *)data;
  697.   register struct arptab *at;
  698.   register struct sockaddr_in *sin;
  699.   struct arptable *atb;
  700.   struct ifaddr *ifa;
  701.   struct sana_softc *ssc;
  702.   spl_t s;
  703.  
  704.   sin = (struct sockaddr_in *)&ar->arp_pa;
  705.   sin->sin_len = sizeof(ar->arp_pa);
  706.  
  707.   if (ar->arp_pa.sa_family != AF_INET ||
  708.       ar->arp_ha.sa_family != AF_UNSPEC)
  709.     return (EAFNOSUPPORT);
  710.  
  711.   s = splimp();
  712.   if ((ifa = ifa_ifwithnet(&ar->arp_pa)) == NULL) {
  713.     splx(s);
  714.     return (ENETUNREACH);
  715.   }
  716.  
  717.   ssc = (struct sana_softc *)ifa->ifa_ifp;
  718.   splx(s);
  719.  
  720.   if (ssc->ss_if.if_type != IFT_SANA || !(atb = ssc->ss_arp.table)) {
  721.     return (EAFNOSUPPORT);
  722.   }
  723.  
  724.   ARPTAB_LOCK(atb);
  725.  
  726.   if (cmd != SIOCGARPT) {
  727.     at = arptab_look(atb, sin->sin_addr.s_addr);
  728.     if (at == NULL && cmd != SIOCSARP) {
  729.       ARPTAB_UNLOCK(atb);
  730.       return (ENXIO);
  731.     }
  732.   }
  733.  
  734.   switch (cmd) {
  735.  
  736.   case SIOCSARP:        /* set entry */
  737.     if (ar->arp_ha.sa_len > sizeof(at->at_hwaddr) + 2 ||
  738.     ar->arp_ha.sa_len != ssc->ss_if.if_addrlen + 2) {
  739.       ARPTAB_UNLOCK(atb);
  740.       return (EINVAL);
  741.     }
  742.     /*
  743.      * Free if new entry should be allocated in a different way 
  744.      */
  745.     if (at != NULL && (at->at_flags ^ ar->arp_flags) & ATF_PERM) {
  746.       arptfree(atb, at);
  747.       at = NULL;
  748.     }
  749.     if (at == NULL) {
  750.       at = arptnew(sin->sin_addr.s_addr, atb, ar->arp_flags & ATF_PERM);
  751.       if (at == NULL) {
  752.     ARPTAB_UNLOCK(atb);
  753.     return (EADDRNOTAVAIL);
  754.       }
  755.     }
  756.  
  757.     bcopy((caddr_t)ar->arp_ha.sa_data, (caddr_t)at->at_hwaddr,
  758.       ar->arp_ha.sa_len - 2);
  759.     at->at_flags = ATF_COM | ATF_INUSE | 
  760.       (ar->arp_flags & (ATF_PERM|ATF_PUBL));
  761.     at->at_timer = 0;
  762.     break;
  763.  
  764.   case SIOCDARP:        /* delete entry */
  765.     arptfree(atb, at);
  766.     break;
  767.  
  768.   case SIOCGARP:        /* get entry */
  769.   case OSIOCGARP:
  770.     bcopy((caddr_t)at->at_hwaddr, (caddr_t)ar->arp_ha.sa_data,
  771.       ar->arp_ha.sa_len = ssc->ss_if.if_addrlen + 2);
  772.     ar->arp_flags = at->at_flags;
  773.     break;
  774.  
  775.   case SIOCGARPT:        /* get table */
  776.     {
  777.       int i, n; long siz;
  778.       register struct arptabreq *atr = (struct arptabreq *)data;
  779.       ar = atr->atr_table;
  780.       siz = ar ? atr->atr_size : 0;
  781.  
  782.       for (n = i = 0; i < ARPTAB_HSIZE; i++) {
  783.     for (at = (struct arptab *)atb->atb_entries[i].mlh_Head; 
  784.          at->at_succ; 
  785.          at = at->at_succ) {
  786.       n++;
  787.       if (siz > 0) {
  788.         struct sockaddr_in *sin = (struct sockaddr_in *)&ar->arp_pa;
  789.         sin->sin_len = sizeof(*sin);
  790.         sin->sin_family = AF_INET;
  791.         sin->sin_addr = at->at_iaddr;
  792.         bcopy((caddr_t)at->at_hwaddr, (caddr_t)ar->arp_ha.sa_data,
  793.           ar->arp_ha.sa_len = ssc->ss_if.if_addrlen + 2);
  794.         ar->arp_flags = at->at_flags;
  795.         siz--;
  796.         ar++;
  797.       }
  798.     }
  799.       }
  800.       atr->atr_size -= siz;
  801.       atr->atr_inuse = n;
  802.     }
  803.   }
  804.  
  805.   ARPTAB_UNLOCK(atb);
  806.   return 0;
  807. }
  808.  
  809. static const char *digits = "0123456789ABCDEF";
  810. /*
  811.  * Print Hardware Address
  812.  */
  813. static char *sana_sprintf(register u_char *ap, int len)
  814. {
  815.   register i;
  816.   static char addrbuf[17*3];
  817.   register unsigned char *cp = addrbuf;
  818.  
  819.   for (i = 0; i < len; ) {
  820.     *cp++ = digits[*ap >> 4];
  821.     *cp++ = digits[*ap++ & 0xf];
  822.     i++;
  823.     if (i < len) 
  824.       *cp++ = ':';
  825.   }
  826.   *cp = 0;
  827.   return (addrbuf);
  828. }
  829.